/*************************************************************
 * Title: 
 * Description: 
 * Author: Snow Huang
 * Email: Shaobin.Software@gmail.com Shaobin_Software@163.com
 * CreateTime: Aug 17, 2010 4:14:53 PM
 * Copyright © 落羽社区 All right reserved
 ************************************************************/
package snow.core.util.algorithm.encoding;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import snow.core.util.algorithm.encoding.codec.Base64;
import snow.core.util.algorithm.encoding.codec.Hex;

/**
 * 
 */
public class MessageDigestPasswordEncoder implements PasswordEncoder {

	private final String algorithm;
	private int iterations = 1;
	private boolean encodeHashAsBase64 = false;

	protected MessageDigestPasswordEncoder(String algorithm) {
		this(algorithm, false);
	}

	private MessageDigestPasswordEncoder(String algorithm, boolean encodeHashAsBase64) {
		this.algorithm = algorithm;
		setEncodeHashAsBase64(encodeHashAsBase64);
		getMessageDigest();
	}

	/**
	 * @param password
	 * @return
	 * @see snow.core.util.algorithm.encoding.PasswordEncoder#encodePassword(java.lang.String)
	 */
	public String encodePassword(String password) {
		MessageDigest messageDigest = getMessageDigest();
		byte[] digest;
		try {
			digest = messageDigest.digest(password.getBytes("UTF-8"));
		} catch (UnsupportedEncodingException e) {
			throw new IllegalStateException("UTF-8 not supported!");
		} catch (Exception e) {
			throw new IllegalStateException(e);
		}
		for (int i = 0; i < iterations; i++) {
			digest = messageDigest.digest(digest);
		}
		if (isEncodeHashAsBase64()) {
			return new String(Base64.encode(digest));
		} else {
			return new String(Hex.encode(digest));
		}
	}

	/**
	 * @return the algorithm
	 */
	public String getAlgorithm() {
		return algorithm;
	}

	/**
	 * @return the iterations
	 */
	public int getIterations() {
		return iterations;
	}

	protected final MessageDigest getMessageDigest() throws IllegalArgumentException {
		try {
			return MessageDigest.getInstance(algorithm);
		} catch (NoSuchAlgorithmException e) {
			throw new IllegalArgumentException("No such algorithm [" + algorithm + "]");
		}
	}

	/**
	 * @return the encodeHashAsBase64
	 */
	public boolean isEncodeHashAsBase64() {
		return encodeHashAsBase64;
	}

	/**
	 * @param encodeHashAsBase64
	 *            the encodeHashAsBase64 to set
	 */
	public void setEncodeHashAsBase64(boolean encodeHashAsBase64) {
		this.encodeHashAsBase64 = encodeHashAsBase64;
	}

	/**
	 * @param iterations
	 *            the iterations to set
	 */
	public void setIterations(int iterations) {
		this.iterations = iterations;
	}
}
